package com.example.up.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.os.RecoverySystem;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.up.MainActivity;
import com.example.up.R;

import com.example.up.view.CommonProgressDialog;
import com.example.up.view.ConfirmDialog;
import com.example.up.view.SingleChoiceDialog;
import com.oazon.mocoupdate.lib.DownloadProgressListener;
import com.oazon.mocoupdate.lib.FileDownloader;
import com.oazon.mocoupdate.lib.FileService;

/**
 * @author coolszy
 * @date 2012-4-26
 * @blog http://blog.92coding.com
 */

public class UpdateManager {
	/* 保存解析的XML信息 */
	HashMap<String, String> mHashMap;
	private static Context mContext;
	private CommonProgressDialog dialog = null;
   
	private ProgressBar mProgress;
	private TextView text1, text2;
	private Dialog mDownloadDialog;
	private Button cancel;
	private static String mProgressNumberFormat;
	private static NumberFormat mProgressPercentFormat;
	private static File updatefile = null;
	private static String md5s = null;

	public UpdateManager(Context context) {

		mContext = context;
		dialog = new CommonProgressDialog(mContext, task);
	}

	public static UpdateManager updateManager;

	public static UpdateManager getInstance(Context context) {
		if (updateManager == null) {
			updateManager = new UpdateManager(context);
			initFormats();
		}

		return updateManager;
	}

	/**
	 * 检测软件更新
	 */
	public void checkUpdate(String server_version, String url) {

		/* if (Integer.parseInt(server_version) >getVersionCode(mContext)) { */

		if (url != null) {
			download(url, new File(Content.path),
					url.substring(url.lastIndexOf('/') + 1), "apk");
            Content.sendStartBoradcast(mContext,"app_update_start");
		}

		/*
		 * } else { Toast.makeText(mContext, R.string.upate_no,
		 * Toast.LENGTH_LONG) .show(); TimerTask task = new TimerTask() {
		 * 
		 * @Override public void run() { // TODO Auto-generated method stub
		 * HttpUtil.start(mContext); } }; Timer time = new Timer();
		 * time.schedule(task, 1000);
		 * 
		 * }
		 */
	}

	/*
	 * 系统更新
	 */
	@SuppressLint("SdCardPath")
	public void checkUpdateota(String server_version, String url, String md5,
			int percent) {
		String sys = getDragonVersion();
		md5s = md5;
		if (url != null) {
		//	if (percent >= 50) {
				// Content.killMoco(mContext);
				deleteFile(new File("/cache/update.zip"));
				updatefile = new File("/cache/update.zip");
				showOTADownloadDialog(url, updatefile);
				 Content.sendStartBoradcast(mContext,"ota_update_start");
			/*} else {
				Toast.makeText(mContext, "电池的电量低于50%,建议您充满电之后再试。",
						Toast.LENGTH_LONG).show();
			}*/
		}
		/*
		 * //"4.4v4.0" "4.4v4.0" server_version服务器版本,sys本地 if
		 * (server_version.compareTo(sys)==1) { updatefile = new
		 * File("/cache/update.zip"); showOTADownloadDialog(url, updatefile); }
		 * else { Toast.makeText(mContext, "服务器版本：" + server_version,
		 * Toast.LENGTH_LONG).show();
		 * 
		 * Toast.makeText(mContext, "系统版本：" + sys, Toast.LENGTH_LONG).show();
		 * 
		 * Toast.makeText(mContext, R.string.ota_update_no, Toast.LENGTH_LONG)
		 * .show(); TimerTask task = new TimerTask() {
		 * 
		 * @Override public void run() { // TODO Auto-generated method stub
		 * HttpUtil.start(mContext); } }; Timer time = new Timer();
		 * time.schedule(task, 1000);
		 * 
		 * }
		 */
	}

	/*
	 * mcu更新
	 */
	@SuppressLint("SdCardPath")
	public void checkUpdateMcu(String version, String server_version,
			String url, int percent) {
		if (url != null) {
			if (percent >= 50) {
				 Content.sendStartBoradcast(mContext,"mcu_update_start");
				new ConfirmDialog(mContext, R.style.notitle, url).show();
			} else {
				Toast.makeText(mContext, "电池的电量低于50%,建议您充满电之后再试。",
						Toast.LENGTH_LONG).show();
			}
		}

		// "04 01" server_version是服务器版本
		/*
		 * if (server_version.compareTo(version) > 0) {
		 * 
		 * if (percent >= 50) { new ConfirmDialog(mContext, R.style.notitle,
		 * url).show(); } else { Toast.makeText(mContext,
		 * "电池的电量低于50%,建议您充满电之后再试。", Toast.LENGTH_LONG).show(); }
		 * 
		 * } else { Toast.makeText(mContext, R.string.ota_update_no,
		 * Toast.LENGTH_LONG) .show(); TimerTask task = new TimerTask() {
		 * 
		 * @Override public void run() { // TODO Auto-generated method stub
		 * HttpUtil.start(mContext); } }; Timer time = new Timer();
		 * time.schedule(task, 1000); }
		 */

	}

	/**
	 * 获取软件版本号
	 * 
	 * @param context
	 * @return
	 */
	private int getVersionCode(Context context) {
		int versionCode = 0;
		try {
			// 获取软件版本号，对应AndroidManifest.xml下android:versionCode
			versionCode = context.getPackageManager().getPackageInfo(
					Content.packger, 0).versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return versionCode;
	}

	/** Hanlder的作用是用于往创建Hander对象所在的线程所绑定的消息队列发送消息 **/
	private Handler handler = new UIHander();

	/**
	 * Hanlder的作用是用于往创建Hander对象所在的线程所绑定的消息队列发送消息
	 */
	private final class UIHander extends Handler {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				msg.getData().getInt("size");
				dialog.setProgress(msg.getData().getInt("size"));
				float num = (float) dialog.getProgress()
						/ (float) dialog.getMax();
				dialog.setTextPercent(num);
				dialog.setTextNumber(msg.getData().getInt("size"),
						dialog.getMax());
				if (dialog.getProgress() == dialog.getMax()) {
					Toast.makeText(mContext, R.string.success, 5000).show();
					dialog.dismiss();

					File apk = task.loader.getFile();
					apk.renameTo(new File(apk.getAbsolutePath().substring(0,
							apk.getAbsolutePath().length() - 3)));
					// installApk(task.loader.getFile());
					installApk(apk.getAbsolutePath().substring(0,
							apk.getAbsolutePath().length() - 4));
			
					Log.i("filetest", task.loader.getFile().getAbsolutePath());
				}
				break;
			case -1:// 下载失败

				Toast.makeText(mContext, R.string.error, Toast.LENGTH_SHORT)
						.show();// 下载出错 break;

				TimerTask task = new TimerTask() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						HttpUtil.start(mContext);
					}
				};
				Timer time = new Timer();
				time.schedule(task, 1000);

				break;

			case -2:// 安装失败
				clean();
				Toast.makeText(mContext, R.string.install, Toast.LENGTH_SHORT)
						.show();// 下载出错 break;
				TimerTask task1 = new TimerTask() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						HttpUtil.start(mContext);
					}
				};
				Timer time1 = new Timer();
				time1.schedule(task1, 1000);
				// showChooseDialog();
				break;

			case -3:// 安装失败
				Toast.makeText(mContext, R.string.timeout, Toast.LENGTH_SHORT)
						.show();// 下载出错 break;
				break;

			}
		}
	}

	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				int size = msg.getData().getInt("size"); // 获取下载的进度值
				mProgress.setProgress(size);
				float num = (float) mProgress.getProgress()
						/ (float) mProgress.getMax();

				setTextPercent(num);
				setTextNumber(size, mProgress.getMax());
				if (mProgress.getProgress() == mProgress.getMax()) {
					Toast.makeText(mContext, R.string.success,
							Toast.LENGTH_LONG).show();
					mDownloadDialog.dismiss();
					if (HttpUtil.getFileMD5(updatefile).equals(md5s)) {
						Toast.makeText(mContext, "md5正确", Toast.LENGTH_SHORT)
								.show();
				
						try {
							RecoverySystem.installPackage(mContext, updatefile);

						} catch (IOException e) {

							e.printStackTrace();
						}
					} else {
						Toast.makeText(mContext, "md5出错了", Toast.LENGTH_SHORT)
								.show();

						TimerTask task = new TimerTask() {

							@Override
							public void run() {
								// TODO Auto-generated method stub
								HttpUtil.start(mContext);
							}
						};
						Timer time = new Timer();
						time.schedule(task, 1000);
					}
				}
				break;
			case -1:// 下载失败
				Toast.makeText(mContext, mContext.getString(R.string.failure),
						Toast.LENGTH_SHORT).show();// 下载出错 break;

				TimerTask task = new TimerTask() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						HttpUtil.start(mContext);
					}
				};
				Timer time = new Timer();
				time.schedule(task, 1000);
				break;
			default:
				break;
			}
		};
	};

	/*
	 * 用路径安装文件
	 */
	/*
	 * private void installApk(String str){ try { Intent install_hide_intent =
	 * new Intent("android.intent.action.VIEW_HIDE"); install_hide_intent
	 * .setDataAndType(Uri.parse("file://" + str),
	 * "application/vnd.android.package-archive");
	 * 
	 * ((Activity)
	 * mContext.getApplicationContext()).startActivityForResult(install_hide_intent
	 * , 1000);
	 * 
	 * 
	 * } catch (Exception e) { handler.sendMessage(handler.obtainMessage(-2)); }
	 * }
	 */
	private void installApk(String str) {
		try {
			Intent install_hide_intent = new Intent(
					"android.intent.action.VIEW");
			install_hide_intent.setDataAndType(Uri.parse("file://" + str),
					"application/vnd.android.package-archive");

			mContext.startActivity(install_hide_intent);

		} catch (Exception e) {
			handler.sendMessage(handler.obtainMessage(-2));
		}
	}

	/*
	 * 用文件安装
	 */
	/*
	 * public void installApk(File apkFile){ try { if(!apkFile.exists()){ return
	 * ; } Intent install_hide_intent = new
	 * Intent("android.intent.action.VIEW.HIDE");
	 * install_hide_intent.setDataAndType
	 * (Uri.fromFile(apkFile),"application/vnd.android.package-archive");
	 * ((Activity)
	 * mContext.getApplicationContext()).startActivityForResult(install_hide_intent
	 * , 1000); } catch (Exception e) {
	 * handler.sendMessage(handler.obtainMessage(-2));
	 * 
	 * } }
	 */
	public void installApk(File apkFile) {
		try {
			if (!apkFile.exists()) {
				return;
			}
			Intent install_hide_intent = new Intent(
					"android.intent.action.VIEW");
			install_hide_intent.setDataAndType(Uri.fromFile(apkFile),
					"application/vnd.android.package-archive");

			mContext.startActivity(install_hide_intent);

		} catch (Exception e) {
			handler.sendMessage(handler.obtainMessage(-2));

		}
	}

	/**
	 * UI控件画面的重绘(更新)是由主线程负责处理的，如果在子线程中更新UI控件的值，更新后的值不会重绘到屏幕上
	 * 一定要在主线程里更新UI控件的值，这样才能在屏幕上显示出来，不能在子线程中更新UI控件的值
	 * 借用Handler来传送UI控件的值到主线程去，在主线程更新UI控件的值
	 */

	/**
	 * 显示软件下载对话框
	 */

	private void showOTADownloadDialog(final String url, File otafile) {
		// 构造软件下载对话框
		System.out.println("构造软件下载对话框");
		// AlertDialog.Builder builder = new Builder(mcon);
		// builder.setTitle(R.string.ota_updating);

		// 给下载对话框增加进度条
		final LayoutInflater inflater = LayoutInflater.from(mContext);
		View v = inflater.inflate(R.layout.dialog_ota, null);
		mProgress = (ProgressBar) v.findViewById(R.id.progress);
		text1 = (TextView) v.findViewById(R.id.progress_percent);
		text2 = (TextView) v.findViewById(R.id.progress_number);
		cancel = (Button) v.findViewById(R.id.cancel);

		mDownloadDialog = new Dialog(mContext, R.style.Dialog_Fullscreen);
		@SuppressWarnings("deprecation")
		LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT);
		mDownloadDialog.addContentView(v, params);

		Window dialogWindow = mDownloadDialog.getWindow();
		WindowManager.LayoutParams lp = dialogWindow.getAttributes();
		dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
		dialogWindow.setGravity(Gravity.CENTER | Gravity.BOTTOM);
		// 显示的坐标
		lp.x = 0;
		lp.y = 1;
		// int width =
		// context1.getResources().getDimensionPixelOffset(R.dimen.d_width);
		// int height =
		// context1.getResources().getDimensionPixelOffset(R.dimen.d_height);
		// dialog的大小
		lp.width = 320;

		dialogWindow.setAttributes(lp);

		mDownloadDialog.show();
		cancel.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				mDownloadDialog.dismiss();
				deleteFile(new File("/cache/update.zip"));
				new FileService(mContext).delete(url);
				HttpUtil.start(mContext);
			}
		});
		download(url, otafile, null, "ota");

	}

	public final class DownloadTask implements Runnable {
		/** 下载路径 */
		private String path;
		/** 保存路径 */
		private File saveDir;
		/** 文件下载器 */
		private FileDownloader loader;

		private String s_type;

		/**
		 * DownloadTask的构造函数
		 * 
		 * @param path
		 *            下载路径
		 * @param saveDir
		 *            保存路径
		 */
		public DownloadTask(String path, File saveDir, String type) {
			this.path = path;
			this.saveDir = saveDir;
			s_type = type;
		}

		/**
		 * 线程主方法
		 */
		public void run() {

			if (s_type.equals("apk")) {
				try {

					/**
					 * 构建文件下载器 将下载路径，文件保存目录，下载线程数指定好
					 */
					loader = new FileDownloader(mContext, path, saveDir, 5,
							"apk");
					dialog.setMax(loader.getFileSize());// 设置进度条的最大刻度（即文件的总长度）
					/**
					 * DownloadProgressListener是一个接口，onDownloadSize()为未实现的方法。
					 * onDownloadSize()方法会在download方法内部被动态赋值
					 * 监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null
					 */
					loader.download(new DownloadProgressListener() {
						public void onDownloadSize(int size) {
							// 借用Handler来传送UI控件的值到主线程去，在主线程更新UI控件的值

							Message msg = new Message();
							msg.what = 1; // 对应UIHander 获得的msg.what
							msg.getData().putInt("size", size); // 将获取的值发送给handler，用于动态更新进度

							handler.sendMessage(msg);
						}
					});

				} catch (Exception e) {
					e.printStackTrace();
					// 对应UIHander 获得的msg.what
					handler.sendMessage(handler.obtainMessage(-1));
				}
			} else if (s_type.equals("ota")) {
				try {
					/**
					 * 构建文件下载器 将下载路径，文件保存目录，下载线程数指定好
					 */
					loader = new FileDownloader(mContext, path, saveDir, 5,
							"ota");
					mProgress.setMax(loader.getFileSize());
					/**
					 * DownloadProgressListener是一个接口，onDownloadSize()为未实现的方法。
					 * onDownloadSize()方法会在download方法内部被动态赋值
					 * 监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null
					 */
					loader.download(new DownloadProgressListener() {
						public void onDownloadSize(int size) {
							// 借用Handler来传送UI控件的值到主线程去，在主线程更新UI控件的值
							Message msg = new Message();
							msg.what = 1; // 对应UIHander 获得的msg.what
							msg.getData().putInt("size", size); // 将获取的值发送给handler，用于动态更新进度
							mHandler.sendMessage(msg);
						}

					});
				} catch (Exception e) {
					e.printStackTrace();
					// 对应UIHander 获得的msg.what
					mHandler.sendMessage(mHandler.obtainMessage(-1));
				}
			}

		}

		/**
		 * 退出下载
		 */
		public void exit() {
			if (loader != null)
				loader.exit();
		}
	}

	/** end of DownloadTask */

	/**
	 * 由于用户的输入事件(点击button, 触摸屏幕....)是由主线程负责处理的，如果主线程处于工作状态，
	 * 此时用户产生的输入事件如果没能在5秒内得到处理，系统就会报“应用无响应”错误。
	 * 所以在主线程里不能执行一件比较耗时的工作，否则会因主线程阻塞而无法处理用户的输入事件，
	 * 导致“应用无响应”错误的出现。耗时的工作应该在子线程里执行。
	 */
	private DownloadTask task;

	/**
	 * 退出下载
	 */
	public void exit() {
		if (task != null)
			task.exit();
	}

	/**
	 * 下载方法，运行在主线程，负责开辟子线程完成下载操作，这操作耗时不超过1秒
	 * 
	 * @param path
	 *            下载路径
	 * @param saveDir
	 *            保存路径name有后缀名
	 */
	public void download(String path, File saveDir, String name, String type) {
		if (type.equals("apk")) {
			if (isExists(saveDir, name)) {
				installApk(Content.path + "/" + name);
			} else {

				dialog.show();
				dialog.setTitleText("正在下载");
				task = new DownloadTask(path, new File(Content.path), "apk");
				new Thread(task).start();// 开辟子线程完成下载操作

			}
		} else if (type.equals("ota")) {
			task = new DownloadTask(path, saveDir, "ota");
			new Thread(task).start();// 开辟子线程完成下载操作

		}

	}

	public String getName(String str) {
		return str.substring(str.lastIndexOf("/") + 1, str.lastIndexOf("."));
	}

	public boolean isExists(String str) {
		File f = new File(Content.path + "/"
				+ str.substring(str.lastIndexOf('/') + 1));
		return f.exists();
	}

	public boolean isExists(File saveDir, String name) {
		File f = new File(Content.path + "/" + name);
		return f.exists();
	}

	public void showChooseDialog() {

		final String url1 = mHashMap.get("url1");
		final String url2 = mHashMap.get("url2");
		List<String> mlist = new ArrayList<String>();
		if (url1 != null && url2 != null) {
			mlist.add(getName(url1));
			mlist.add(getName(url2));
		}

		final SingleChoiceDialog mSingleChoiceDialog = new SingleChoiceDialog(
				mContext, mlist);
		mSingleChoiceDialog.setTitle("请您选择之前的版本。");
		mSingleChoiceDialog
				.setOnOKButtonListener(new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						int selItem = mSingleChoiceDialog.getSelectItem();
						// Toast.makeText(mcon, "selItem = " + selItem,
						// Toast.LENGTH_SHORT).show();
						if (selItem == 0) {
							download(url1, new File(Content.path),
									url1.substring(url1.lastIndexOf('/') + 1),
									"apk");
						} else if (selItem == 1) {
							download(url2, new File(Content.path),
									url2.substring(url1.lastIndexOf('/') + 1),
									"apk");
						}
					}
				});

		mSingleChoiceDialog.show();

	}

	public void clean() {

		File f = new File(Content.path);

		File[] fl = f.listFiles();
		for (int i = 0; i < fl.length; i++) {
			if (fl[i].toString().endsWith(".apk")) {
				if (fl[i].delete()) {
					Toast.makeText(mContext,
							mContext.getString(R.string.c_success),
							Toast.LENGTH_LONG).show();
				} else {
					Toast.makeText(mContext,
							mContext.getString(R.string.c_failue),
							Toast.LENGTH_LONG).show();
				}
			}
		}
	}

	public static boolean checkURL(String url) {
		boolean value = false;
		try {
			HttpURLConnection conn = (HttpURLConnection) new URL(url)
					.openConnection();
			int code = conn.getResponseCode();
			System.out.println(">>>>>>>>>>>>>>>> " + code
					+ " <<<<<<<<<<<<<<<<<<");
			if (code != 200) {
				value = false;
			} else {
				value = true;
			}
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return value;
	}

	/**
	 * 获取软件版本号
	 * 
	 * @return
	 */
	public String getDragonVersion() {
		String str1 = "/system/build.prop";
		return LogsReaderWriter.readFromFile(str1, "ro.product.firmware")
				.substring(20).substring(0, 7);

	}

	public void deleteFile(File file) {
		if (file.exists()) { // 判断文件是否存在
			if (file.isFile()) { // 判断是否是文件
				file.delete(); // delete()方法 你应该知道 是删除的意思;
			} else if (file.isDirectory()) { // 否则如果它是一个目录
				File files[] = file.listFiles(); // 声明目录下所有的文件 files[];
				for (int i = 0; i < files.length; i++) { // 遍历目录下所有的文件
					this.deleteFile(files[i]); // 把每个文件 用这个方法进行迭代
				}
			}
			file.delete();
		} else {

		}

	}

	private static void initFormats() {
		mProgressNumberFormat = "%1.2fM/%2.2fM";
		mProgressPercentFormat = NumberFormat.getPercentInstance();
		mProgressPercentFormat.setMaximumFractionDigits(0);
	}

	public void setTextPercent(float percent) {
		if (mProgressPercentFormat != null) {
			SpannableString tmp = new SpannableString(
					mProgressPercentFormat.format(percent));
			tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0,
					tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
			text1.setText(tmp);
		} else {
			text1.setText("");
		}
	}

	public void setTextNumber(int progress, int max) {

		double dProgress = (double) progress / (double) (1024 * 1024);
		double dMax = (double) max / (double) (1024 * 1024);
		if (mProgressNumberFormat != null) {
			String format = mProgressNumberFormat;
			text2.setText(String.format(format, dProgress, dMax));
		} else {
			text2.setText("");
		}
	}
	
	
	
	
}
